package com.lzx.hbh_system.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzx.hbh_system.bo.dict.Dicts;
import com.lzx.hbh_system.bo.xqzhxxgl.BuildingInfo;
import com.lzx.hbh_system.bo.xqzhxxgl.VillageInfo;
import com.lzx.hbh_system.dto.DictsDto;
import com.lzx.hbh_system.dto.DictsDtoStronger;
import com.lzx.hbh_system.mapper.DictsMapper;
import com.lzx.hbh_system.mapper.xqzhxxgl.BuildingInfoMapper;
import com.lzx.hbh_system.mapper.xqzhxxgl.VillageInfoMapper;
import com.lzx.hbh_system.service.DictsService;
import com.lzx.hbh_system.util.RedisUtils;
import com.lzx.hbh_system.util.responseEntity.RespOutMsgHeader;
import com.lzx.hbh_system.util.responseEntity.ResponseView;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DictsServiceImpl extends ServiceImpl<DictsMapper, Dicts> implements DictsService {
    @Autowired
    private DictsMapper dictsMapper;
    @Autowired
    private VillageInfoMapper villageInfoMapper;
    @Autowired
    private BuildingInfoMapper buildingInfoMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ModelMapper modelMapper;
    // Redis更新判断参数 - 仅仅当开发人员使用，且不能向外泄露
    static final String updateCode = "UpDaTe";
    @Override
    public ResponseView getDictsByType(String dictsType) { // 查询各类状态字典
        // 初始化参数
        ResponseView responseView = new ResponseView();
        if(dictsType.contains(updateCode)){
            // 先删除redis对应key的内容
            redisUtils.delete("AllDictsListKey");
            String[] requestArray = null;
            requestArray = dictsType.split("-",2);
            String dictsTypeStr = requestArray[0];
            System.out.println(dictsTypeStr);
            // 返回新数据
            List<Dicts> dicts = getOrSetRedisDictsList();
            dicts = dicts.stream().filter(item -> item.getDictType().equals(dictsTypeStr)).sorted(Comparator.comparing(Dicts::getLevel)).collect(Collectors.toList());
            // 返回消息
            responseView.setRespOutMsgHeader(RespOutMsgHeader.success(dicts.size(),"查询成功"));
            responseView.setMain(dicts.toArray());
            return responseView;
        }
        List<Dicts> dicts = getOrSetRedisDictsList();
        dicts = dicts.stream().filter(item -> item.getDictType().equals(dictsType)).sorted(Comparator.comparing(Dicts::getLevel)).collect(Collectors.toList());
        // 返回消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success(dicts.size(),"查询成功"));
        responseView.setMain(dicts.toArray());
        return responseView;
    }
    @Override
    public ResponseView getTreeDictsByType(String dictsType) { // 查询仅有一个孩子的字典
        // 初始化参数
        ResponseView responseView = new ResponseView();
        if(dictsType.contains(updateCode)){
            log.info("开启更新Redis字典内容，更新类型："+dictsType);
            // 先删除redis对应key的内容
            redisUtils.delete("AllDictsListKey");
            String[] requestArray = null;
            requestArray = dictsType.split("-",2);
            String dictsTypeStr = requestArray[0];
            System.out.println(dictsTypeStr);
            // 返回新数据
            List<Dicts> dicts = getOrSetRedisDictsList();
            dicts = dicts.stream().filter(item -> item.getDictType().equals(dictsTypeStr)).sorted(Comparator.comparing(Dicts::getLevel)).collect(Collectors.toList());
            List<DictsDto> Treedicts = transferNormalDictsListToTreeDicts(dicts,dictsType);
            // 返回消息
            responseView.setRespOutMsgHeader(RespOutMsgHeader.success(Treedicts.size(),"查询成功"));
            responseView.setMain(Treedicts.toArray());
            return responseView;
        }
        List<Dicts> dicts = getOrSetRedisDictsList();
        List<DictsDto> Treedicts = transferNormalDictsListToTreeDicts(dicts,dictsType);
        // 返回消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success(Treedicts.size(),"查询成功"));
        responseView.setMain(Treedicts.toArray());
        return responseView;
    }

    @Override
    public ResponseView getTreeMapDictsByType(String dictsType) { // 查询有多个孩子的字典
        // 初始化参数
        ResponseView responseView = new ResponseView();
        if(dictsType.contains(updateCode)){
            // 先删除redis对应key的内容
            redisUtils.delete("AllDictsListKey");
            String[] requestArray = null;
            requestArray = dictsType.split("-",2);
            String dictsTypeStr = requestArray[0];
            // 返回新数据
            List<Dicts> dicts = getOrSetRedisDictsList();
            dicts = dicts.stream().filter(item -> item.getDictType().equals(dictsTypeStr)).sorted(Comparator.comparing(Dicts::getLevel)).collect(Collectors.toList());
            List<DictsDtoStronger> Treedicts = transferNormalDictsListToTreeDictsStronger(dicts,dictsType);
            // 返回消息
            responseView.setRespOutMsgHeader(RespOutMsgHeader.success(Treedicts.size(),"查询成功"));
            responseView.setMain(Treedicts.toArray());
            return responseView;
        }
        List<Dicts> dicts = getOrSetRedisDictsList();
        List<DictsDtoStronger> Treedicts = transferNormalDictsListToTreeDictsStronger(dicts,dictsType);
        // 返回消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success(Treedicts.size(),"查询成功"));
        responseView.setMain(Treedicts.toArray());
        return responseView;
    }

    /**
     * 获取或者设置所有Dicts内容到Redis
     * @Synchronized （它可以防止不同的线程同时执行同一段代码）避免了多个程序同时访问的并发出现 redis同时存在空数据且push相同数据进入redis导致查询重复的问题。
     * 会导致效率变低，只能等待一个程序调用执行完毕才释放资源 给下一个使用！
     * @return
     */
    @Synchronized
    public List<Dicts> getOrSetRedisDictsList(){
        // 查询Redis
        List<Object> objects = redisUtils.getList("AllDictsListKey"); // 查询redis所有的字典信息
        System.out.println("当前字典redis存在的内容长度为：" + objects.size());
        if (objects.size() == 0){
            // redis 初始为空的情况
            // 查询数据库信息放入redis中
            QueryWrapper<Dicts> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByAsc("id");
            List<Dicts> dictlist = dictsMapper.selectList(queryWrapper);
            log.info("将数据库的数据Push至Redis中");
            redisUtils.lRightPushAll("AllDictsListKey",dictlist);
            return dictlist;
        }
        // redis不为空的情况下 返回redis的所有字典内容
        return transferList(redisUtils.getList("AllDictsListKey"));
    }
    /**
     * 将普通查询对应类型的 字典列表  算法转换成 父子树结构的字典列表
     * @param dicts
     * @return
     */
    public List<DictsDto> transferNormalDictsListToTreeDicts(List<Dicts> dicts,String dictsType){
        List<DictsDto> dictsDtos = null;
        try {
            dictsDtos = new ArrayList<>();
            List<DictsDto> finalDictList = dictsDtos;
            dicts.forEach(item -> {
                DictsDto dictsDto = new DictsDto();
                modelMapper.map(item,dictsDto);
                if(Objects.equals(item.getParentCode(), "0")){
                    // 父节点
                    QueryWrapper<Dicts> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("dict_type",dictsType);
                    queryWrapper.eq("parent_code",item.getId());
                    queryWrapper.orderByAsc("level");
                    List<Dicts> dictsList = dictsMapper.selectList(queryWrapper);
                    dictsDto.setChildren(dictsList);
                    finalDictList.add(dictsDto);
                }
            });
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return dictsDtos;
    }
    /**
     * 将普通查询对应类型的 字典列表  算法转换成 父子树结构的字典列表
     * 结合了小区和楼号信息 所有是强化版的树结构
     * @param dicts
     * @return
     */
    public List<DictsDtoStronger> transferNormalDictsListToTreeDictsStronger(List<Dicts> dicts,String dictsType){
        List<DictsDtoStronger> DictListDictsDtoStrongerList = null;
        try {
            DictListDictsDtoStrongerList = new ArrayList<>();
            List<DictsDtoStronger> finalDictListDictsDtoStrongerList = DictListDictsDtoStrongerList;
            dicts.forEach(item -> {
                if(Objects.equals(item.getParentCode(), "0")){
                    // 父节点
                    QueryWrapper<Dicts> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("dict_type",dictsType);
                    queryWrapper.eq("parent_code",item.getId());
                    queryWrapper.orderByAsc("level");
                    List<Dicts> dictsList = dictsMapper.selectList(queryWrapper);
                    List<DictsDtoStronger> dictsitemDictsDtoStrongerList = getVilaAndBuildMap(dictsList);
                    DictsDtoStronger dictsDtoStronger = new DictsDtoStronger();
                    dictsDtoStronger.setValue(item.getValue());
                    dictsDtoStronger.setCode(item.getCode());
                    dictsDtoStronger.setChildren(dictsitemDictsDtoStrongerList);
                    finalDictListDictsDtoStrongerList.add(dictsDtoStronger);
                }
            });
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return DictListDictsDtoStrongerList;
    }
    public List<DictsDtoStronger> getVilaAndBuildMap(List<Dicts> dictsList){
        List<DictsDtoStronger> dictsDtoStrongerList = new ArrayList<>();
        dictsList.forEach(item -> {
            DictsDtoStronger dictsDtoStronger = new DictsDtoStronger();
            String cotyCode = item.getCode(); // 拿到每个子字典的 区县编号
            QueryWrapper<VillageInfo> queryWrapper = new QueryWrapper();
            queryWrapper.eq("coty_code",cotyCode);
            List<VillageInfo> villageInfos = villageInfoMapper.selectList(queryWrapper); // 拿到对应每个子区县的小区信息列表
            List<DictsDtoStronger> villageInfoDictsDtoStrongerList = new ArrayList<>();
            villageInfos.forEach(item2 ->{
                String villageKey = item2.getId();
                DictsDtoStronger villageInfoDictsdictsDtoStronger = new DictsDtoStronger();
                villageInfoDictsdictsDtoStronger.setValue(item2.getVillageName());
                villageInfoDictsdictsDtoStronger.setCode(item2.getId());
                QueryWrapper<BuildingInfo> queryWrapper2 = new QueryWrapper();
                queryWrapper2.eq("village_code",villageKey);
                List<BuildingInfo> buildingInfos = buildingInfoMapper.selectList(queryWrapper2); // 拿到对应每个小区的楼号列表
                List<DictsDtoStronger> buildingInfoDictsDtoStrongerList = new ArrayList<>();
                buildingInfos.forEach(item3 ->{
                    DictsDtoStronger buildingInfoDtoStronger = new DictsDtoStronger();
                    buildingInfoDtoStronger.setValue(item3.getBuildingNumber());
                    buildingInfoDtoStronger.setCode(item3.getId());
                    buildingInfoDictsDtoStrongerList.add(buildingInfoDtoStronger);
                });
                villageInfoDictsdictsDtoStronger.setChildren(buildingInfoDictsDtoStrongerList);
                villageInfoDictsDtoStrongerList.add(villageInfoDictsdictsDtoStronger);
            });
            dictsDtoStronger.setValue(item.getValue());
            dictsDtoStronger.setCode(item.getCode());
            dictsDtoStronger.setChildren(villageInfoDictsDtoStrongerList);
            dictsDtoStrongerList.add(dictsDtoStronger);
        });
        return dictsDtoStrongerList;
    }
    /**
     * Redis Object转换函数
     * @param list
     * @return
     */
    public List<Dicts> transferList(List<Object> list){
        List<Dicts> redisDictList = null;
        try {
            redisDictList = new ArrayList<>();
            List<Dicts> finalRedisDictList = redisDictList;
            list.forEach(item->{
                Dicts dicts = JSONObject.parseObject(item.toString(),Dicts.class);
                finalRedisDictList.add(dicts);
            });
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return redisDictList;
    }

//    /**
//     * Redis Object转换函数 - Tree结构的列表
//     * @param list
//     * @return
//     */
//    public List<DictsDto> transferTreeList(List<Object> list){
//        List<DictsDto> redisTreeDictList = null;
//        try {
//            redisTreeDictList = new ArrayList<>();
//            List<DictsDto> finalRedisDictList = redisTreeDictList;
//            list.forEach(item->{
//                DictsDto treedicts = JSONObject.parseObject(item.toString(),DictsDto.class);
//                finalRedisDictList.add(treedicts);
//            });
//        } catch (Exception e) {
//            log.error(e.getMessage());
//        }
//        return redisTreeDictList;
//    }
//    /**
//     * Redis Object转换函数 - Tree结构的列表 - 强化版
//     * @param list
//     * @return
//     */
//    public List<DictsDtoStronger> transferTreeListStronger(List<Object> list){
//        System.out.println(list);
//        List<DictsDtoStronger> redisTreeDictList = null;
//        try {
//            redisTreeDictList = new ArrayList<>();
//            List<DictsDtoStronger> finalRedisDictList = redisTreeDictList;
//            list.forEach(item->{
//                DictsDtoStronger treedicts = JSONObject.parseObject((byte[]) JSONObject.parse(item.toString()),DictsDtoStronger.class);
//                finalRedisDictList.add(treedicts);
//            });
//        } catch (Exception e) {
//            log.error(e.getMessage());
//        }
//        return redisTreeDictList;
//    }
}
